package com.zoght.financial.parser;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import com.zoght.financial.model.TransactionBean;

public class BMOTxParser {

	private BufferedReader m_reader;
	
	public BMOTxParser(String filenamePath) throws IOException {
	    try {
	    	m_reader = new BufferedReader(new FileReader(filenamePath));
	    } catch (IOException e) {
	    	throw e;
	    }
	}
	
	public List<TransactionBean> parse() {
		List<TransactionBean> l = new LinkedList<TransactionBean>();
		try {
	        String str;
	        while ((str = m_reader.readLine()) != null) {
	            TransactionBean bean = process(str);
	            if (bean != null) {
	            	l.add(bean);
	            }
            }
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		finally {
	        try {
				m_reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return l;

	}
	
	private Date getDate(String dateStr) {
		assert(dateStr != null);
	    SimpleDateFormat sdf = new SimpleDateFormat
		     ("yyyy-MM-dd", Locale.US);
	    try {
		    return sdf.parse(dateStr);
	    } catch (ParseException pex) {
	    	return null;
	    }
	}
	
	private TransactionBean.Type getType(String type) {
		assert(type != null);
		if (type.equals("Buy")) {
			return TransactionBean.Type.Buy;
		} else if (type.equals("Sell")) {
			return TransactionBean.Type.Sell;
		} else if (type.equals("Dividend")) {
			return TransactionBean.Type.Dividend;
		} else if (type.equals("Interest")) {
			return TransactionBean.Type.Interest;
		} else if (type.equals("Telephone Banking")) {
			return TransactionBean.Type.TelephoneBanking;
		} else {
		    return null;
		}
	}
	
	private double getDouble(String doubleStr) {
		assert(doubleStr !=null);
		try {
			return Double.parseDouble(doubleStr);
		} catch (NumberFormatException nex) {
			return Double.MAX_VALUE;
		}
	}
	
	private int getInteger(String intStr) {
		assert(intStr !=null);
		try {
			return Integer.parseInt(intStr);
		} catch (NumberFormatException nex) {
			return Integer.MAX_VALUE;
		}
	}
	
	private TransactionBean process(String str) {
		if (!str.startsWith("2")) {
			return null;
		}
	    StringTokenizer strTokenizer = new StringTokenizer(str,",");
	    TransactionBean bean = new TransactionBean();
	    try {
	       String txDateStr = strTokenizer.nextToken();
           bean.setTransactionDate(getDate(txDateStr));
           String settleDateStr = strTokenizer.nextToken();
           bean.setSettlemenDate(getDate(settleDateStr));
           String typeStr = strTokenizer.nextToken();
           bean.setType(getType(typeStr));
           if (bean.getType() == TransactionBean.Type.Interest) {
        	   // Parse interest
        	   bean.setDescription(strTokenizer.nextToken());
        	   String totalStr = strTokenizer.nextToken();
        	   bean.setTotal(getDouble(totalStr));
        	   return bean;
           } else if (bean.getType() == TransactionBean.Type.Dividend) {
        	   // Dividend
        	   bean.setDescription(strTokenizer.nextToken());
        	   bean.setSymbol(strTokenizer.nextToken());
        	   String totalStr = strTokenizer.nextToken();
        	   bean.setTotal(getDouble(totalStr));
        	   return bean;
           } else if (bean.getType() == TransactionBean.Type.TelephoneBanking) {
        	   // Telephone banking
        	   bean.setDescription(strTokenizer.nextToken());
        	   String totalStr = strTokenizer.nextToken();
        	   bean.setTotal(getDouble(totalStr));
        	   return bean;
           } else {
        	   bean.setDescription(strTokenizer.nextToken());
        	   bean.setSymbol(strTokenizer.nextToken());
        	   String quantityStr = strTokenizer.nextToken();
        	   bean.setUnits(getInteger(quantityStr));
        	   String pricePerUnitStr = strTokenizer.nextToken();
        	   bean.setPricePerUnit(getDouble(pricePerUnitStr));
        	   strTokenizer.nextToken();// currency, CAD for now
        	   String totalStr = strTokenizer.nextToken();
        	   bean.setTotal(getDouble(totalStr));
        	   return bean;
           }
	       
	    } catch (NoSuchElementException nsex) {
	       return bean;
	    }
	    		
	}
}
